package org.custom.spring.boot.transaction.service.async;

import lombok.SneakyThrows;
import org.custom.spring.boot.transaction.async.AsyncCall;
import org.custom.spring.boot.transaction.entity.Transaction;
import org.custom.spring.boot.transaction.mapper.TransactionMapper;
import org.custom.spring.boot.transaction.utils.ValidUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.concurrent.ExecutionException;

/**
 * 异步事务服务
 *
 * @author LiKun
 * @date 2021/9/17 8:44
 */
@Service
public class AsyncTransactionService {
    @Resource
    private AsyncCall asyncCall;
    @Resource
    private TransactionMapper transactionMapper;

    @Transactional
    public int transaction(String data1, String data2) {
        transactionMapper.insert(Transaction.getInstance(data1));
        asyncCall.transactionException(data2);
        return ValidUtil.byZero();
    }

    @Transactional
    public int validAsyncTransactionInternal(String data1, String data2) throws ExecutionException, InterruptedException {
        transactionMapper.insert(Transaction.getInstance(data1));
        return asyncCall.asyncWithTransactionalAndException(data2).get();
    }

    @Transactional
    public int validAsyncWithoutTransaction(String data1, String data2) throws ExecutionException, InterruptedException {
        transactionMapper.insert(Transaction.getInstance(data1));
        return asyncCall.asyncWithoutTransactional(data2).get();
    }

    public int validAsyncWithoutTransactionInternal(String data1, String data2) throws ExecutionException, InterruptedException {
        transactionMapper.insert(Transaction.getInstance(data1));
        return asyncCall.asyncWithTransactionalAndException(data2).get();
    }

    /**
     * 校验 a 异步调用 B，同时 B 捕获异常并手动回滚事务(注：即使 B 没有捕获异常，a 也无法捕获 B 抛出的异常)
     *
     * @param data 测试数据
     *
     * @return 返回结果
     */
    @SneakyThrows
    @Transactional
    public int valid_a_Async_B_And_a_Catch_B_Exception(String data) {
        transactionMapper.selectById(data);
        return asyncCall.exception_and_manual_rollback_transaction(data).get();
    }
}
